package com.example.lock;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ShardRabbitLockManager {
    private static final Logger log = LoggerFactory.getLogger(ShardRabbitLockManager.class);
    private Map<String, List<ShardRabbitLock>> stringShardRabbitLockMap = new HashMap();

    public ShardRabbitLockManager() {
    }

    public void add(ShardRabbitLock shardRabbitLock) {
        String queueNamePrefix = shardRabbitLock.getQueueNamePrefix();
        List<ShardRabbitLock> shardRabbitLocks = (List)this.stringShardRabbitLockMap.get(queueNamePrefix);
        if (shardRabbitLocks == null) {
            shardRabbitLocks = new ArrayList();
            this.stringShardRabbitLockMap.put(queueNamePrefix, shardRabbitLocks);
        }

        ((List)shardRabbitLocks).add(shardRabbitLock);
    }

    public void checkLock(int instanceSize) {
        Set<Entry<String, List<ShardRabbitLock>>> entries = this.stringShardRabbitLockMap.entrySet();
        Iterator var3 = entries.iterator();

        while(true) {
            List shardRabbitLocks;
            int hasLockCount;
            int shardSize;
            String queueName;
            do {
                do {
                    if (!var3.hasNext()) {
                        return;
                    }

                    Entry<String, List<ShardRabbitLock>> entry = (Entry)var3.next();
                    shardRabbitLocks = (List)entry.getValue();
                    hasLockCount = 0;
                    shardSize = 0;
                    queueName = (String)entry.getKey();
                    Iterator var9 = shardRabbitLocks.iterator();

                    while(var9.hasNext()) {
                        ShardRabbitLock shardRabbitLock = (ShardRabbitLock)var9.next();
                        shardRabbitLock.checkLock();
                        shardSize = shardRabbitLock.getSize();
                        if (shardRabbitLock.hasLock()) {
                            ++hasLockCount;
                        }
                    }
                } while(instanceSize < shardSize);
            } while(hasLockCount <= 1);

            log.info("start to release surplus lock, queueName:{},instanceSize:{},shardSize:{},hasLockCount:{}", new Object[]{queueName, instanceSize, shardSize, hasLockCount});
            int count = 0;
            Iterator var13 = shardRabbitLocks.iterator();

            while(var13.hasNext()) {
                ShardRabbitLock shardRabbitLock = (ShardRabbitLock)var13.next();
                if (shardRabbitLock.hasLock()) {
                    ++count;
                }

                if (count > 1) {
                    shardRabbitLock.releaseLock();
                }
            }
        }
    }

    private void tryLock(String queueNamePrefix, String servieName, int instanceSize, long timeout) {
        List<ShardRabbitLock> shardRabbitLocks = (List)this.stringShardRabbitLockMap.get(queueNamePrefix);
        boolean hasLock = false;
        Iterator var8 = shardRabbitLocks.iterator();

        ShardRabbitLock shardRabbitLock;
        while(var8.hasNext()) {
            shardRabbitLock = (ShardRabbitLock)var8.next();
            if (shardRabbitLock.hasLock()) {
                hasLock = true;
                break;
            }
        }

        boolean result;
        if (!hasLock) {
            var8 = shardRabbitLocks.iterator();

            while(var8.hasNext()) {
                shardRabbitLock = (ShardRabbitLock)var8.next();
                result = false;
                if (timeout <= 0L) {
                    result = shardRabbitLock.tryLock();
                } else {
                    result = shardRabbitLock.tryLock(timeout);
                }

                if (result) {
                    break;
                }
            }
        } else {
            var8 = shardRabbitLocks.iterator();

            while(var8.hasNext()) {
                shardRabbitLock = (ShardRabbitLock)var8.next();
                if (instanceSize < shardRabbitLock.getSize()) {
                    result = false;
                    if (timeout <= 0L) {
                        result = shardRabbitLock.tryLock();
                    } else {
                        result = shardRabbitLock.tryLock(timeout);
                    }

                    log.info("some instances are down, try to take lock from others, service name:{},instance size:{},result:{},key:{}", new Object[]{servieName, instanceSize, result, shardRabbitLock.key()});
                    if (result) {
                        break;
                    }
                }
            }
        }

    }

    public void tryLock(String queueNamePrefix, String servieName, int instanceSize) {
        this.tryLock(queueNamePrefix, servieName, instanceSize, -1L);
    }

    public void initTryLock(String queueNamePrefix, String servieName, int instanceSize) {
        this.tryLock(queueNamePrefix, servieName, instanceSize, 60L);
    }

    public void tryAllLock(String servieName, int instanceSize) {
        Set<Entry<String, List<ShardRabbitLock>>> entries = this.stringShardRabbitLockMap.entrySet();
        Iterator var4 = entries.iterator();

        while(var4.hasNext()) {
            Entry<String, List<ShardRabbitLock>> entry = (Entry)var4.next();
            String key = (String)entry.getKey();
            this.tryLock(key, servieName, instanceSize);
        }

    }

    public void initTryAllLock(String servieName, int instanceSize) {
        Set<Entry<String, List<ShardRabbitLock>>> entries = this.stringShardRabbitLockMap.entrySet();
        Iterator var4 = entries.iterator();

        while(var4.hasNext()) {
            Entry<String, List<ShardRabbitLock>> entry = (Entry)var4.next();
            String key = (String)entry.getKey();
            this.initTryLock(key, servieName, instanceSize);
        }

    }

    public void fresh() {
        Set<Entry<String, List<ShardRabbitLock>>> entries = this.stringShardRabbitLockMap.entrySet();
        Iterator var2 = entries.iterator();

        while(var2.hasNext()) {
            Entry<String, List<ShardRabbitLock>> entry = (Entry)var2.next();
            List<ShardRabbitLock> shardRabbitLocks = (List)entry.getValue();
            Iterator var5 = shardRabbitLocks.iterator();

            while(var5.hasNext()) {
                ShardRabbitLock shardRabbitLock = (ShardRabbitLock)var5.next();
                if (shardRabbitLock.hasLock()) {
                    boolean result = shardRabbitLock.freshLock();
                    if (!result) {
                        log.info("fresh lock fail key:{}", shardRabbitLock.key());
                    }
                }
            }
        }

    }
}
